#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NSA5312 ADC数据采集界面
ADC Collection Widget for NSA5312

基于export_fuce.txt分析的ADC获取序列:
1. NSA5312采集64通道 (0x63) - 超时参数00
2. 获取温度校准数据 (0x62)
3. 启动ADC采集 (0x40)
4. 获取ADC数据 (0x41)
"""

import sys
import time
import struct
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
                           QPushButton, QGroupBox, QGridLayout, QTextEdit, 
                           QProgressBar, QSpinBox, QCheckBox, QComboBox,
                           QMessageBox, QTableWidget, QTableWidgetItem,
                           QHeaderView, QTabWidget, QLineEdit)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QColor, QPalette

from serial_handler import NSA5312CommandHelper
from serial_protocol import CommandCode, StatusCode

class ADCCollectionThread(QThread):
    """ADC数据采集线程"""
    
    progress_update = pyqtSignal(int, str)  # 进度, 消息
    adc_data_update = pyqtSignal(int, int, int)  # 行, 列, ADC值
    collection_complete = pyqtSignal(bool, str, dict)  # 成功状态, 消息, 数据字典
    
    def __init__(self, command_helper, collection_params):
        super().__init__()
        self.command_helper = command_helper
        self.collection_params = collection_params
        self.is_running = True
        
    def run(self):
        """执行ADC数据采集"""
        try:
            self.progress_update.emit(10, "开始ADC数据采集序列...")
            
            # 步骤1: NSA5312采集64通道 (0x63)
            if self.collection_params.get('use_nsa5312', True):
                self.progress_update.emit(20, "执行NSA5312 64通道采集 (0x63)...")
                timeout_param = self.collection_params.get('timeout', 0)
                success = self.nsa5312_collect(timeout_param)
                if not success:
                    self.collection_complete.emit(False, "NSA5312采集失败", {})
                    return
            
            time.sleep(0.5)  # 等待采集完成
            
            # 步骤2: 获取温度校准数据 (0x62)
            if self.collection_params.get('get_temperature', True):
                self.progress_update.emit(40, "获取温度校准数据 (0x62)...")
                temp_data = self.get_temperature_data()
                if not temp_data:
                    self.progress_update.emit(45, "温度数据获取失败，继续ADC采集...")
            
            # 步骤3: 启动ADC采集 (0x40)
            self.progress_update.emit(60, "启动ADC采集 (0x40)...")
            success = self.collect_adc()
            if not success:
                self.collection_complete.emit(False, "ADC采集启动失败", {})
                return
            
            time.sleep(1.0)  # 等待ADC采集完成
            
            # 步骤4: 获取ADC数据 (0x41)
            self.progress_update.emit(80, "获取ADC数据 (0x41)...")
            adc_data = self.get_adc_data()
            
            if adc_data:
                # 解析ADC数据并更新UI
                self.parse_and_update_adc_data(adc_data)
                self.progress_update.emit(100, "ADC数据采集完成")
                
                # 生成统计信息
                stats = self.generate_adc_statistics(adc_data)
                self.collection_complete.emit(True, f"成功采集{len(adc_data)}个ADC值", stats)
            else:
                self.collection_complete.emit(False, "ADC数据获取失败", {})
            
        except Exception as e:
            self.collection_complete.emit(False, f"采集异常: {str(e)}", {})
    
    def nsa5312_collect(self, timeout_param):
        """NSA5312 64通道数据采集 (0x63)"""
        try:
            params = bytes([timeout_param])
            response = self.command_helper.send_custom_command(0x63, params)
            return response.success
        except:
            return False
    
    def get_temperature_data(self):
        """获取温度校准数据 (0x62)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.OWI_64CH_TEMP_SEND)
            return response.data if response.success else None
        except:
            return None
    
    def collect_adc(self):
        """启动ADC采集 (0x40)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_COLLECT)
            return response.success
        except:
            return False
    
    def get_adc_data(self):
        """获取ADC数据 (0x41)"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_SEND)
            return response.data if response.success else None
        except:
            return None
    
    def parse_and_update_adc_data(self, adc_data):
        """解析ADC数据并更新UI"""
        if not adc_data or len(adc_data) < 128:  # 64通道 * 2字节 = 128字节
            return
        
        # 解析16位ADC值 (大端序)
        for i in range(64):
            if i * 2 + 1 < len(adc_data):
                # 从字节数据中提取16位ADC值
                adc_value = struct.unpack('>H', adc_data[i*2:i*2+2])[0]
                
                # 计算行列位置 (0-based)
                row = i // 8
                col = i % 8
                
                # 发送更新信号 (转换为1-based)
                self.adc_data_update.emit(row + 1, col + 1, adc_value)
    
    def generate_adc_statistics(self, adc_data):
        """生成ADC统计信息"""
        if not adc_data or len(adc_data) < 128:
            return {}
        
        adc_values = []
        for i in range(64):
            if i * 2 + 1 < len(adc_data):
                adc_value = struct.unpack('>H', adc_data[i*2:i*2+2])[0]
                adc_values.append(adc_value)
        
        if adc_values:
            return {
                'count': len(adc_values),
                'min': min(adc_values),
                'max': max(adc_values),
                'avg': sum(adc_values) / len(adc_values),
                'non_zero': len([v for v in adc_values if v > 0])
            }
        return {}
    
    def stop(self):
        """停止采集"""
        self.is_running = False

class ADCCollectionWidget(QWidget):
    """NSA5312 ADC数据采集控件"""
    
    def __init__(self, command_helper: NSA5312CommandHelper):
        super().__init__()
        self.command_helper = command_helper
        self.collection_thread = None
        self.adc_data = {}  # 存储ADC数据
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        layout = QVBoxLayout()
        
        # ADC采集控制组
        control_group = QGroupBox("ADC采集控制 (基于export_fuce.txt序列)")
        control_layout = QGridLayout()
        
        # 采集参数
        control_layout.addWidget(QLabel("NSA5312超时参数:"), 0, 0)
        self.timeout_spin = QSpinBox()
        self.timeout_spin.setRange(0, 255)
        self.timeout_spin.setValue(0)  # 默认0=无超时
        self.timeout_spin.setToolTip("0x63命令的超时参数，0表示无超时")
        control_layout.addWidget(self.timeout_spin, 0, 1)
        
        # 采集选项
        self.use_nsa5312_cb = QCheckBox("使用NSA5312命令 (0x63)")
        self.use_nsa5312_cb.setChecked(True)
        control_layout.addWidget(self.use_nsa5312_cb, 0, 2)
        
        self.get_temperature_cb = QCheckBox("获取温度数据 (0x62)")
        self.get_temperature_cb.setChecked(True)
        control_layout.addWidget(self.get_temperature_cb, 0, 3)
        
        # 主要操作按钮
        full_sequence_btn = QPushButton("执行完整ADC采集序列")
        full_sequence_btn.clicked.connect(self.start_full_adc_collection)
        control_layout.addWidget(full_sequence_btn, 1, 0, 1, 2)
        
        stop_btn = QPushButton("停止采集")
        stop_btn.clicked.connect(self.stop_adc_collection)
        control_layout.addWidget(stop_btn, 1, 2)
        
        # 单步操作按钮
        control_layout.addWidget(QLabel("单步操作:"), 2, 0)
        
        nsa5312_btn = QPushButton("NSA5312采集 (0x63)")
        nsa5312_btn.clicked.connect(self.single_nsa5312_collect)
        control_layout.addWidget(nsa5312_btn, 2, 1)
        
        temp_btn = QPushButton("获取温度 (0x62)")
        temp_btn.clicked.connect(self.single_get_temperature)
        control_layout.addWidget(temp_btn, 2, 2)
        
        adc_collect_btn = QPushButton("采集ADC (0x40)")
        adc_collect_btn.clicked.connect(self.single_collect_adc)
        control_layout.addWidget(adc_collect_btn, 3, 1)
        
        adc_get_btn = QPushButton("获取ADC (0x41)")
        adc_get_btn.clicked.connect(self.single_get_adc)
        control_layout.addWidget(adc_get_btn, 3, 2)
        
        control_group.setLayout(control_layout)
        layout.addWidget(control_group)
        
        # 进度显示
        progress_group = QGroupBox("采集进度")
        progress_layout = QVBoxLayout()
        
        self.progress_bar = QProgressBar()
        progress_layout.addWidget(self.progress_bar)
        
        self.progress_label = QLabel("就绪")
        progress_layout.addWidget(self.progress_label)
        
        progress_group.setLayout(progress_layout)
        layout.addWidget(progress_group)
        
        # ADC数据显示表格
        adc_display_group = QGroupBox("64通道ADC数据显示")
        adc_display_layout = QVBoxLayout()
        
        # 创建8x8 ADC显示表格
        self.adc_table = QTableWidget()
        self.adc_table.setRowCount(8)
        self.adc_table.setColumnCount(8)
        self.adc_table.setMaximumHeight(300)
        
        # 设置表头
        row_headers = [f"行{i+1}" for i in range(8)]
        col_headers = [f"列{i+1}" for i in range(8)]
        self.adc_table.setVerticalHeaderLabels(row_headers)
        self.adc_table.setHorizontalHeaderLabels(col_headers)
        
        # 初始化ADC表格
        self.init_adc_table()
        
        # 自适应列宽
        self.adc_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        adc_display_layout.addWidget(self.adc_table)
        
        # ADC统计信息和控制
        stats_layout = QHBoxLayout()
        
        stats_layout.addWidget(QLabel("统计:"))
        self.adc_stats_label = QLabel("未采集")
        stats_layout.addWidget(self.adc_stats_label)
        
        stats_layout.addStretch()
        
        clear_btn = QPushButton("清空数据")
        clear_btn.clicked.connect(self.clear_adc_data)
        stats_layout.addWidget(clear_btn)
        
        export_btn = QPushButton("导出数据")
        export_btn.clicked.connect(self.export_adc_data)
        stats_layout.addWidget(export_btn)
        
        adc_display_layout.addLayout(stats_layout)
        adc_display_group.setLayout(adc_display_layout)
        layout.addWidget(adc_display_group)
        
        # 详细日志
        log_group = QGroupBox("采集日志")
        log_layout = QVBoxLayout()
        
        self.log_text = QTextEdit()
        self.log_text.setMaximumHeight(150)
        self.log_text.setFont(QFont("Courier", 9))
        log_layout.addWidget(self.log_text)
        
        log_group.setLayout(log_layout)
        layout.addWidget(log_group)
        
        self.setLayout(layout)
    
    def init_adc_table(self):
        """初始化ADC数据表格"""
        for row in range(8):
            for col in range(8):
                sensor_num = row * 8 + col + 1
                item = QTableWidgetItem("0")
                item.setTextAlignment(Qt.AlignCenter)
                
                # 特别标识24号传感器
                if sensor_num == 24:
                    item.setBackground(QColor(255, 255, 224))  # 浅黄色
                    item.setText("0 (24号)")
                    item.setToolTip("24号传感器 - 应该有ADC数据")
                else:
                    item.setBackground(QColor(245, 245, 245))  # 浅灰色
                    item.setToolTip(f"传感器{sensor_num}")
                
                self.adc_table.setItem(row, col, item)
    
    def start_full_adc_collection(self):
        """开始完整ADC采集序列"""
        if self.collection_thread and self.collection_thread.isRunning():
            QMessageBox.warning(self, "警告", "采集正在进行中")
            return
        
        # 准备采集参数
        collection_params = {
            'timeout': self.timeout_spin.value(),
            'use_nsa5312': self.use_nsa5312_cb.isChecked(),
            'get_temperature': self.get_temperature_cb.isChecked()
        }
        
        # 创建并启动采集线程
        self.collection_thread = ADCCollectionThread(self.command_helper, collection_params)
        self.collection_thread.progress_update.connect(self.update_progress)
        self.collection_thread.adc_data_update.connect(self.update_adc_value)
        self.collection_thread.collection_complete.connect(self.collection_completed)
        
        self.collection_thread.start()
        self.log_message("开始执行完整ADC采集序列...")
    
    def stop_adc_collection(self):
        """停止ADC采集"""
        if self.collection_thread:
            self.collection_thread.stop()
            self.collection_thread.wait(3000)
        
        self.progress_label.setText("采集已停止")
        self.log_message("ADC采集已停止")
    
    def update_progress(self, progress, message):
        """更新进度"""
        self.progress_bar.setValue(progress)
        self.progress_label.setText(message)
    
    def update_adc_value(self, row, col, adc_value):
        """更新ADC值显示"""
        if 1 <= row <= 8 and 1 <= col <= 8:
            item = self.adc_table.item(row-1, col-1)
            if item:
                sensor_num = (row-1) * 8 + col
                
                # 更新显示文本
                if sensor_num == 24:
                    item.setText(f"{adc_value} (24号)")
                    if adc_value > 0:
                        item.setBackground(QColor(144, 238, 144))  # 浅绿色 - 有数据
                    else:
                        item.setBackground(QColor(255, 182, 193))  # 浅红色 - 无数据
                else:
                    item.setText(str(adc_value))
                    if adc_value > 0:
                        item.setBackground(QColor(220, 220, 220))  # 浅灰色 - 有数据
                
                # 保存数据
                self.adc_data[sensor_num] = adc_value
    
    def collection_completed(self, success, message, stats):
        """采集完成"""
        if success:
            self.log_message(f"✅ {message}")
            if stats:
                stats_text = f"总数:{stats.get('count', 0)}, 非零:{stats.get('non_zero', 0)}, "
                stats_text += f"最小:{stats.get('min', 0)}, 最大:{stats.get('max', 0)}, "
                stats_text += f"平均:{stats.get('avg', 0):.1f}"
                self.adc_stats_label.setText(stats_text)
        else:
            self.log_message(f"❌ {message}")
        
        # 显示结果对话框
        QMessageBox.information(self, "采集完成", message)
    
    # 单步操作函数
    def single_nsa5312_collect(self):
        """单步：NSA5312采集"""
        try:
            timeout_param = self.timeout_spin.value()
            params = bytes([timeout_param])
            response = self.command_helper.send_custom_command(0x63, params)
            
            if response.success:
                self.log_message(f"✅ NSA5312采集成功 (超时参数: {timeout_param})")
            else:
                self.log_message(f"❌ NSA5312采集失败: {response.error_msg}")
        except Exception as e:
            self.log_message(f"❌ NSA5312采集异常: {str(e)}")
    
    def single_get_temperature(self):
        """单步：获取温度数据"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.OWI_64CH_TEMP_SEND)
            
            if response.success:
                data_len = len(response.data) if response.data else 0
                self.log_message(f"✅ 温度数据获取成功 ({data_len}字节)")
            else:
                self.log_message(f"❌ 温度数据获取失败: {response.error_msg}")
        except Exception as e:
            self.log_message(f"❌ 温度数据获取异常: {str(e)}")
    
    def single_collect_adc(self):
        """单步：采集ADC"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_COLLECT)
            
            if response.success:
                self.log_message("✅ ADC采集启动成功")
            else:
                self.log_message(f"❌ ADC采集启动失败: {response.error_msg}")
        except Exception as e:
            self.log_message(f"❌ ADC采集启动异常: {str(e)}")
    
    def single_get_adc(self):
        """单步：获取ADC数据"""
        try:
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_SEND)
            
            if response.success and response.data:
                data_len = len(response.data)
                self.log_message(f"✅ ADC数据获取成功 ({data_len}字节)")
                
                # 解析并显示数据
                self.parse_adc_response(response.data)
            else:
                self.log_message(f"❌ ADC数据获取失败: {response.error_msg}")
        except Exception as e:
            self.log_message(f"❌ ADC数据获取异常: {str(e)}")
    
    def parse_adc_response(self, adc_data):
        """解析ADC响应数据"""
        if not adc_data or len(adc_data) < 128:
            self.log_message(f"⚠️ ADC数据长度不足: {len(adc_data)}字节 (期望至少128字节)")
            return
        
        # 解析64个16位ADC值
        valid_count = 0
        for i in range(64):
            if i * 2 + 1 < len(adc_data):
                adc_value = struct.unpack('>H', adc_data[i*2:i*2+2])[0]
                row = i // 8 + 1
                col = i % 8 + 1
                
                self.update_adc_value(row, col, adc_value)
                if adc_value > 0:
                    valid_count += 1
        
        self.log_message(f"✅ 解析完成: 64个通道, {valid_count}个有效值")
        
        # 更新统计
        if self.adc_data:
            values = [v for v in self.adc_data.values() if v > 0]
            if values:
                stats_text = f"有效值:{len(values)}, 最小:{min(values)}, 最大:{max(values)}, 平均:{sum(values)/len(values):.1f}"
                self.adc_stats_label.setText(stats_text)
    
    def clear_adc_data(self):
        """清空ADC数据"""
        self.adc_data.clear()
        self.init_adc_table()
        self.adc_stats_label.setText("未采集")
        self.progress_bar.setValue(0)
        self.progress_label.setText("就绪")
        self.log_message("ADC数据已清空")
    
    def export_adc_data(self):
        """导出ADC数据"""
        if not self.adc_data:
            QMessageBox.warning(self, "警告", "没有ADC数据可导出")
            return
        
        from PyQt5.QtWidgets import QFileDialog
        filename, _ = QFileDialog.getSaveFileName(
            self, "导出ADC数据", "adc_data.csv", "CSV Files (*.csv);;All Files (*)"
        )
        
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write("传感器编号,行,列,ADC值\\n")
                    
                    for sensor_num in range(1, 65):
                        row = (sensor_num - 1) // 8 + 1
                        col = (sensor_num - 1) % 8 + 1
                        adc_value = self.adc_data.get(sensor_num, 0)
                        f.write(f"{sensor_num},{row},{col},{adc_value}\\n")
                
                self.log_message(f"✅ ADC数据已导出到: {filename}")
                QMessageBox.information(self, "成功", f"ADC数据已导出到:\\n{filename}")
            except Exception as e:
                self.log_message(f"❌ 导出失败: {str(e)}")
                QMessageBox.critical(self, "错误", f"导出失败: {str(e)}")
    
    def log_message(self, message):
        """记录日志消息"""
        from datetime import datetime
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.append(f"[{timestamp}] {message}")
        
        # 自动滚动到底部
        cursor = self.log_text.textCursor()
        cursor.movePosition(cursor.End)
        self.log_text.setTextCursor(cursor)